/*
   Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
   Original sources are available at www.latestbit.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package org.latestbit.smartobjects.network;

import java.nio.ByteBuffer;

/**
 * ConnectionHandler store information about network connection, 
 * managed connection and their coordinator. 
 * Also connectionHandler handling all events occurs on network connection and 
 * pass them to managed connection.
 * @author abdulla-a
 *
 */
public class ConnectionHandler implements IConnectionListener, IStreamListener {
	
	private IConnection connection;
	private IEndpointCoordinator coordinator;
	private ManagedConnection managedConnection;
	
	public ConnectionHandler(IConnection connection, IEndpointCoordinator coordinator) {
		this.connection = connection;
		this.coordinator = coordinator;
	}

	@Override
	public synchronized void onConnected(IConnection connection) {
		if ( this.coordinator.onConnected ( this ) == IEndpointCoordinator.ManagedConnectionStatus.CONNECTED ) { 
			if(managedConnection!=null) {
				managedConnection.fireOnConnected();
			}
		}

		if(managedConnection!=null) {
			managedConnection.fireOnConnected(this);
		}
	}

	@Override
	public synchronized void onConnectionFailure(IConnection connection, String errorMessage) {
		if ( this.coordinator.onConnectionFailure(this, errorMessage) == IEndpointCoordinator.ManagedConnectionStatus.DISCONNECTED ) {
			if(managedConnection!=null) {
				managedConnection.fireOnConnectionFailure ( this, errorMessage );
				managedConnection.fireOnConnectionFailure ( errorMessage );
			}
		}
		else
		if(managedConnection!=null)
			managedConnection.fireOnConnectionFailure ( this, errorMessage );		
	}

	@Override
	public synchronized void onDisconnected(IConnection connection) {

		// Store copy of managed connection if this is changed by coordinator
		ManagedConnection managedConnectionCopy = managedConnection;
		
		if ( this.coordinator.onDisconnected ( this ) == IEndpointCoordinator.ManagedConnectionStatus.DISCONNECTED) { 
			if(managedConnectionCopy!=null) {
				managedConnectionCopy.fireOnDisconnected(this);
				managedConnectionCopy.fireOnDisconnected();
			}
		}
		else
			if(managedConnectionCopy!=null) {
				managedConnectionCopy.fireOnDisconnected(this);
			}			
	}


	@Override
	public synchronized void onReceived(IConnection connection, ByteBuffer buffer) {
		// this.coordinator.onReceived ( this, buffer );

		if(managedConnection!=null) {
			managedConnection.fireOnReceived(this, buffer);
		}
	}

	@Override
	public synchronized void onReceiveError(IConnection connection, String errorMessage) {
		if(managedConnection!=null) {
			managedConnection.fireOnReceiveError(this, errorMessage);
		}
	}

	@Override
	public synchronized  void onWriteError(IConnection connection, String errorMessage) {
		if(managedConnection!=null) {
			managedConnection.fireOnWriteError(this, errorMessage);
		}
	}

	protected synchronized void setManagedConnection(ManagedConnection managedConnection) {
		this.managedConnection = managedConnection;
	}

	public synchronized IManagedConnection getManagedConnection() {
		return managedConnection;
	}

	public IConnection getConnection() {
		return connection;
	}

	public IEndpointCoordinator getCoordinator() {
		return this.coordinator;
	}
}
